package com.juma.cartridge.rlock.aop;

import java.lang.reflect.Method;

import javax.annotation.Resource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import com.juma.cartridge.rlock.LockManager;

@Aspect
public class LockAspect {

    @Resource
    private LockManager lockManager;
    
    
	@Pointcut("@annotation(com.juma.cartridge.rlock.aop.Lock)")
	public void retryPoint() {}
	
	@Around("retryPoint()")
	public void intercept(ProceedingJoinPoint point) throws Throwable {
		
		Lock annot  = getLockAnnotation(point);
		String key = KeyParseUtils.parse(annot.key(), point.getArgs());
		com.juma.cartridge.rlock.Lock lc = lockManager.getLock(key, annot.lockSeconds(), annot.fair());
		try {
	        lc.acquire(annot.retryWaitTimes());
		    point.proceed();
		}finally{
		    if(lc!=null) {
		        lc.release();    
		    }
		}
	}
	
	
	private Lock getLockAnnotation(ProceedingJoinPoint pjp) {
		Signature sig = pjp.getSignature();
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			return null;
		}
		msig = (MethodSignature) sig;
		Object target = pjp.getTarget();
		try {
			Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
			return currentMethod.getAnnotation(Lock.class);
		}catch(Exception e){
			return null;
		}
	}

    public void setLockManager(LockManager lockManager) {
        this.lockManager = lockManager;
    }
	
	
}
